#include "etcd.h"

#include <string>

#include "log.h"

namespace chat {
// Registry

Registry::Registry(const std::string& host)
    : client_(std::make_shared<etcd::Client>(host)),
      keep_alive_(client_->leasekeepalive(3).get()),
      lease_id_(keep_alive_->Lease()) {}

bool Registry::registry(const std::string& key, const std::string& val) {
    auto resp = client_->put(key, val, lease_id_).get();
    if (resp.is_ok() == false) {
        LOG_ERROR("新增数据失败 {}", resp.error_message());
        return false;
    }

    LOG_DEBUG("注册服务: {}-{}", key, val);

    return true;
}

// -------------------------------------------------------------------

// Discovery

Discovery::Discovery(const std::string& host, const std::string& base_dir,
                     callback_t put_cb, callback_t del_cb)
    : client_(std::make_shared<etcd::Client>(host)),
      put_cb_(put_cb),
      del_cb_(del_cb) {
    discovery(base_dir);
}

void Discovery::discovery(const std::string& base_dir) {
    // 1. 首先进行服务发现
    auto resp = client_->ls(base_dir).get();
    if (resp.is_ok() == false) {
        LOG_ERROR("获取键值对数据失败 {}", resp.error_message());
    }

    int size = resp.keys().size();
    for (int i = 0; i < size; ++i) {
        if (put_cb_) {
            put_cb_(resp.key(i), resp.value(i).as_string());
        }
    }

    // 2. 然后开始监视关心的服务
    watcher_ = std::make_shared<etcd::Watcher>(
        *client_.get(), base_dir,
        std::bind(&Discovery::callback, this, std::placeholders::_1), true);
}

void Discovery::callback(const etcd::Response& resp) {
    if (resp.is_ok() == false) {
        LOG_ERROR("收到一个错误事件通知 {}", resp.error_message());
        return;
    }

    for (auto& ev : resp.events()) {
        if (ev.event_type() == etcd::Event::EventType::PUT) {
            LOG_DEBUG("服务信息新增: {}-{}", ev.kv().key(),
                      ev.kv().as_string());
            if (put_cb_) {
                put_cb_(ev.kv().key(), ev.kv().as_string());
            }

        } else if (ev.event_type() == etcd::Event::EventType::DELETE_) {
            LOG_DEBUG("服务信息下线: {}-{}", ev.prev_kv().key(),
                      ev.prev_kv().as_string());
            if (del_cb_) {
                del_cb_(ev.prev_kv().key(), ev.prev_kv().as_string());
            }
        }
    }
}
}  // namespace chat
